define(function(require, exports){
	var $ = require('jquery');
	var pubjs = require('pubjs');
	var view  = require('@base/view');
	var plupload = require('@libs/plupload/plupload.full.min');
	var DONE = 5; // 设置完成状态为5
	var util = require('util');
	var common = require('modules/common');
	var CryptoJS = require('md5');

	var Uploader = view.container.extend({
		init: function(config){
			config = pubjs.conf(config, {
				'filters': {},					// 限制上传文件的类型，大小等
				'hasProgress': true,				// 是否要创建进度条
				'subModule': '',
				'uploadId': '',						//指定id.
				'hasTip': true,
				'title': LANG('选择文件'),
				'url' : '/api/dsp/upload',			// 服务器端的上传页面地址
				'hasClose': false,
				'class': 'uk-form M-uploader'
			});

			this.$data = {};

			this.$idToName = {};

			// 上传成功个数
			this.$count = 0;

			// children's id counter
			this.$idNum = 0;

			if(window.File && window.FileReader)
			{
				//todo 先隐藏h5的快传。
				//this.$isH5 = true;
				//this.$isH5 = true;
			}

			this.Super('init', arguments);
		},
		afterBuild: function(layout){
			var self = this;
			var c = this.getConfig();

			// 生成id随机数
			var uploaderId = c.uploadId ? c.uploadId : ('uploaderButtonId_' +util.random());
			this.append($([
				'<div class="M-uploaderContainer"/>',
				c.hasProgress ? '<div pub-name="progress" pub-mod="modules/upload.progress" />' : '',
				'<input class="M-uploaderInput btn btn-default-gradient" type="button" id="'+uploaderId+'" value="'+LANG(c.title)+'"/>',
				'<i class="icon-close cur_p""></i>'
			].join('')));

			if(c.hasClose) {
				this.find('.icon-close').bind('click', function() {
					self.reset();
				});
			}
			else {
				this.find('.icon-close').hide();
			}

			if(c.hasTip) {
				this.append('<div pub-name="tips" pub-mod="@base/tip.desc" class="M-uploaderTips"/>');
				c.tips = {
					width: 300,
					data: LANG(c.tips)
				}
			}
			// 触发文件选择对话框的按钮，为那个元素id
			c.browse_button = uploaderId;
			var config = $.extend({}, c, {
				// 使用 flash 先，是因为html5的不能很好地过滤文件类型，好像你只过滤flv,
				// 连图片也会显示出来，这是官方的bug.如有flash 就没有这个问题
				runtimes : 'html5,flash,silverlight,gears,browserplus',
				flash_swf_url: PUBJS("libs") + '/plupload/Moxie.swf',
				silverlight_xap_url: PUBJS("libs") + '/plupload/Moxie.xap'
			});

			var uploader = this.$uploader = plupload.worker(config);
			uploader.init();
			// 定时去刷新上传器的位置，其实也可以需求的时候调用，这里只是为了以防没有调用到，自动刷新一下。
			setInterval(function() {
				uploader.refresh();
			}, 1000);



			self.bindEvents(uploader);
			self.buildFromTemplate(c);
		},
		removeItem: function(id) {
			if (util.isObject(id)) {
				id = id.id;
			}
			var name = this.$idToName[id];
			var mod = name && this.get(name);
			this.$uploader.removeFile(id);
			if (mod) {
				mod.destroy();
			}
			return this;
		},
		buildItem: function(data){
			var c = this.getConfig();
			var el = this.getDOM();

			var name = 'child_'+(this.$idNum++);
			// 将id映射到模块名
			this.$idToName[data.id] = name;

			// 创建子项目
			this.createAsync(name, c.subModule, util.extend({}, {
				data: data,
				fileId: data.id,
				target: el.find('.M-uploaderContainer')
			}, c.sub_conf || {}));
		},
		buildItems: function(data) {
			var i = 0
				, len = data.length;

			//单选
			if(this.getConfig('multi_selection') === false){
				this.reset();
				len = len > 0 ? 1 : 0;
			}

			for(; i<len; i++){
				this.buildItem(data[i]);
			}

			return len;
		},

		/** ---------- 文件上传事件 ---------- **/

		bindEvents: function(self){
			self.bind('FilesAdded',this.filesAdded.bind(this));
			self.bind('UploadProgress',this.uploadProgress.bind(this));
			self.bind('FileUploaded',this.fileUploaded.bind(this));
			self.bind('UploadComplete',this.uploadComplete.bind(this));
			self.bind('Error',this.uploadError.bind(this));
		},
		checkMd5File: function(uploader, files, num) {
			var self = this;
			if(num < files.length)
			{
				var tmp = files[num].getNative();
				var fileReader = new FileReader();
				var blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice;
				var mdStr = '';
				//文件每块分割2M，计算分割详情
				var chunkSize = 2097152;
				var chunks = Math.ceil(tmp.size / chunkSize);
				var currentChunk = 0;
				//处理单片文件的上传
				function loadNext() {
					var start = currentChunk * chunkSize;
					var end = (start + chunkSize) >= tmp.size ? tmp.size : start + chunkSize;
					fileReader.readAsText(blobSlice.call(tmp, start, end));
				}

				fileReader.onload = function(e) {
					//console.log("读取文件", currentChunk + 1, "/", chunks);
					mdStr += e.target.result;
					currentChunk++;
					//如果文件处理完成计算MD5，如果还有分片继续处理
					if (currentChunk < chunks) {
						loadNext();
					}
					else
					{
						var url = self.getConfig('url');
						mdStr = CryptoJS.MD5(mdStr);
						pubjs.data.post(url.replace('upload', 'fast_upload'), {fileName: tmp.name ,code: mdStr.toString()},function(param) {
							if(param && param.exists)
							{
								files[num].status = DONE;
								self.fileUploaded(uploader, files[num], param);
							}

							setTimeout(function() {
								self.checkMd5File(uploader, files, ++num);
							}, 0);
						});
					}
				};

				loadNext();
			}
			else
			{
				uploader.start();
				this.updateProgressAmount();
				pubjs.loading.hide();
			}
		},
		// 文件成功添加到上传队列事件
		filesAdded: function(uploader,files){
			this.$data.length = this.buildItems(files);
			if(this.$isH5 && files && files[0] && files[0].getNative && files[0].getNative() instanceof window.File)
			{
				pubjs.loading.show();
				this.checkMd5File(uploader, files, 0);
			}
			else
			{
				uploader.start();
				this.updateProgressAmount();
			}
		},
		// 文件上传进度事件
		uploadProgress: function(uploader,file){
			this.cast('uploadProgress', file);
			this.fire('uploadProgress', file);
			this.updateProgress(file);
		},
		// 队列中的单个文件上传完成事件
		fileUploaded: function(uploader,file,res){
			var result;
			if(util.isString(res.response))
			{
				result = $.parseJSON(res.response);
			}
			else
			{
				result = res;
			}
			if(result.error || result.code){
				pubjs.alert(result.error || result.message);
				this.cast('uploadError', {'file':file});
				this.fire('uploadError', {'file':file});
				return false;
			}

			if(!result.data){
				pubjs.alert(LANG('无返回数据'));
			}else{
				file.data = result.data;
				this.cast('fileUploaded', [file, result.data]);
				this.fire('fileUploaded', [file, result.data]);
				this.$flag++;
				this.$count++;
				this.updateProgressAmount();
			}
		},
		// 上传队列中所有文件都上传完成事件
		uploadComplete: function(uploader,files){
			this.$data = {};
			this.$count = 0;

			this.cast('uploadComplete', files);
			this.fire('uploadComplete', files);

			this.$uploader.refresh();
			if(this.$.progress){
				this.$.progress.reset();
			}

			if(this.getConfig('subModule').match('whisky') != null){
				this.disable();
			}
		},
		// 错误处理
		processError: function(err, c) {
			var message = err.message;
			switch(err.code) {
				case -500:
					message = LANG("初始化错误");
				break;
				case -600:
					message = LANG("文件尺寸不能超过%1", c.filters && c.filters.max_file_size);
				break;
				case -601:
					message = LANG("不被允许的文件类型");
				break;
				case -602:
					message = LANG("上传文件重复");
				break;
			}
			pubjs.alert(message);
			return this;
		},
		// 文件上传失败事件
		uploadError: function(uploader, err){
			this.processError(err, this.getConfig());
			this.cast('uploadError', err);
			this.fire('uploadError', err);
		},

		/** ---------- 操作 ---------- **/
		// 更新总数信息
		updateProgressAmount: function(){
			var mod = this.$.progress;
			if(mod){
				mod.show();
				mod.updateTitle(this.$count+'/'+this.$data.length);
			}
		},
		updateProgress: function(file){
			var num = +this.$data.length;
			var percent = (file.percent / ((num-this.$count)*100))*100;
			var mod = this.$.progress;
			if(mod){
				mod.show();
				mod.updateBar(percent);
			}
		},
		disable: function(){
			if(this.$.tips) {
				this.$.tips.hide();
			}
			this.getDOM().find('.M-uploaderInput').prop('disabled', true).hide();
			return false;
		},
		enable: function(){
			if(this.$.tips) {
				this.$.tips.show();
			}

			var el = this.getDOM();
			if(el && el.find)
			{
				this.getDOM().find('.M-uploaderInput').prop('disabled', false).show();
			}

			return false;
		},
		onChildDeleted: function(){
			if(this.getConfig('subModule').match('whisky') != null){
				this.enable();
			}
			return false;
		},
		/** ---------- 数据 ---------- **/
		getValue: function(){
			var value = [];
			var subs = this.$;
			for (var e in subs){
				if(e.match('child_')!= null){
					value.push(subs[e].getValue())
				}
			}
			return value;
		},
		setValue: function(data){
			data = util.isArray(data) ? data : [data];
			this.buildItems(data);

			if(this.getConfig('subModule').match('whisky') != null){
				this.disable();
			}
		},
		reset: function(){
			this.enable();
			var subs = this.$;
			subs.progress && subs.progress.reset();
			this.$idToName = {};
			for (var e in subs){
				if(e.match('child_')!= null){
					subs[e].destroy();
				}
			}
			return this;
		},
		clearFiles: function()
		{
			if (this.$uploader && this.$uploader.splice)
			{
				var files = this.$uploader.files || [];
				this.$uploader.splice(0, files.length);
			}
		}
	});
	exports.base = Uploader;

	var AdminUploader = Uploader.extend({
		init: function(config){
			config = pubjs.conf(config, {
				'url' : '/api/admin/oemUpload'		// 服务器端的上传页面地址
			});

			this.Super('init', arguments);
		}
	});
	exports.admin = AdminUploader;


	// 进度条模块
	var Progress  = view.container.extend({
		init: function(config){
			config = pubjs.conf(config, {
				'class': 'M-uploaderProgress',
				'width': 420
			});

			this.Super('init', arguments);
		},
		afterBuild: function(layout){
			var self = this;
			var c = self.getConfig();
			var el = self.getDOM();
			var doms = self.$doms = {};
			self.append($([
					'<div class="countCon b-is-gray">',
						'<span class="count font-gray"/>',
					'</div>',
					'<div class="barCon b-is-gray">',
						'<div class="bar b-is-success"/>',
					'</div>'
			].join('')));

			doms.countCon = el.find('.countCon');
			doms.count = el.find('.count');
			doms.barCon = el.find('.barCon');
			doms.bar = el.find('.bar');


			if(c.width){
				el.width(c.width);
			}

			doms.barCon.width(el.width() - doms.countCon.width() - 10);
		},
		updateTitle: function(text){
			this.$doms.count.text(text);
			return this;
		},
		updateBar: function(num){
			this.$doms.bar.css('width', num + '%');
			return this;
		},
		reset: function(){
			this.$doms.bar.css('width', 0);
			this.$el.hide();
			return this;
		}
	});
	exports.progress = Progress;


	// 上传组件辅助控件 -状态，按钮
	var UploaderAssist = view.container.extend({
		init: function(config){
			config = pubjs.conf(config, {
				'hasDelete': true,			// 删除功能
				'hasPreview': false,		// 预览功能
				'hasDone': true,		// 预览功能
				'class': 'M-uploaderAssist'
			});

			this.$data = config.get('data');

			this.Super('init', arguments);
		},
		afterBuild: function(){
			var c = this.getConfig();
			var el = this.getDOM();

			$([
				'<div class="M-uploaderAssistDesc">'+LANG('等待上传')+'</div>',
				'<div class="M-uploaderAssistBar"><div class="bar b-is-success"/></div>',
				'<div class="M-uploaderAssistButton">',
					'<span class="hyperlink preview" data-type="preview">'+LANG('预览')+'</span>',
				'</div>',
				'<div class="M-uploaderAssistButton">',
					'<span class="hyperlink delete" data-type="delete">'+LANG('删除')+'</span>',
				'</div>'
			].join('')).appendTo(el);

			if(!c.hasPreview){
				el.find('.preview').hide();
			}
			if(!c.hasDelete){
				el.find('.delete').hide();
			}

			var config = {

			};

			this.buildFromTemplate(config);

			this.$doms = {
				barCon: el.find('.M-uploaderAssistBar'),
				bar: el.find('.M-uploaderAssistBar .bar'),
				desc: el.find('.M-uploaderAssistDesc')
			};

			this.uiProxy(el, '.M-uploaderAssistButton span', 'click', 'eventButtonClick');
		},
		showPreview: function()
		{
			if(this.$previewUrl){
				window.open(this.$previewUrl);
			}else{
				pubjs.alert(LANG('暂无预览图'));
			}
		},
		eventButtonClick: function(evt, elm){
			var name = $(elm).attr('data-type');
			switch(name){
				case 'preview':
					this.showPreview();
				break;
				case 'delete':
					this.fire('childDeleted', null, 'afterChildDeleted', this);
				break;
			}
			return false;
		},
		eventDelete: function(ev){
			this.fire('childDeleted', null, 'afterChildDeleted', this);
			return false;
		},
		afterChildDeleted: function(){
			this.destroy();
		},
		// 更新状态
		update: function(status){
			var doms = this.$doms;

			switch(status){
				case false:
					doms.barCon.hide();
					doms.desc.addClass('font-danger').text(LANG('上传失败'));
				break;
				case true:
					doms.barCon.hide();
					if(!this.getConfig('hasDone')) {
						doms.desc.hide();
					}
					else {
						doms.desc.show();
					}
					doms.desc.html('<i class="done uk-icon-check-circle font-success"/>');
				break;
				default:
					doms.barCon.show();
					doms.bar.css('width', status+'%');
					doms.desc.text(LANG('上传中(')+status+'%)');
				break;
			}
		},
		setData: function(data){
/*			var c = this.getConfig();
			var url = pubjs.config('materialPreview')[c.type];
			if(url){
				// 有预览地址时
				this.$previewUrl = url.replace('{id}', data.id);
			}else{
			}*/

			this.$previewUrl = data && data.previewUrl;
			return this;
		},
		setPreview: function(url) {
/*			var c = this.getConfig();
			var has = pubjs.config('materialPreview')[c.type];
			if(url && !has) {
			}*/
			this.$previewUrl = url;
			return this;
		},
		reset: function(){
			this.$previewUrl = '';
			this.$doms.desc.removeClass('font-danger');
			this.$doms.bar.css('width', 0);
			this.$doms.barCon.hide();
		}
	});
	exports.assist = UploaderAssist;



/** -------------------- 业务 -------------------- **/
	// 上传封面
	var Cover = view.container.extend({
		init: function(config){
			config = pubjs.conf(config, {
				'fileId': 0,
				'data': null,
				'class': 'M-uploaderCover',
				'defaultImage': window.ROOT('resources/images/default.png')
			});

			this.$data = null;

			this.$fileId = config.get('fileId');

			this.Super('init', arguments);
		},
		afterBuild: function(){
			var c = this.getConfig();

			this.append('<div class="M-uploaderCoverThumb"><img alt="'+LANG('封面')+'" src="'+c.defaultImage+'" /></div>');

			// 控制状态模块
			this.create('assist', UploaderAssist, {
				'hasDelete': false,
				'target': this.$el,
				'hasPreview': true,
				'class': 'M-uploaderCoverStatus'
			});

			if(c.data){
				this.$.assist.update(true);
				this.setData(c.data);
			}
		},
		getData: function(){
			return this.$data;
		},
		onUploadProgress: function(ev){
			var file = ev.param;
			if(this.$fileId == file.id){
				this.$.assist.update(file.percent);
			}
		},
		onFileUploaded: function(ev){
			var file = ev.param[0];
			var data = ev.param[1];

			if(this.$fileId == file.id){
				this.$.assist.update(true);
				this.setData(data);
			}
		},
		onUploadError: function(ev){
			var file = ev.param.file;
			if(this.$fileId == file.id){
				this.$.assist.update(false);
			}
		},
		setData: function(data){
			if ( typeof data === "string" ) {
				data = {thumb : data};
			}

			var cover = {};
			cover.thumb = data.thumb ? (data.thumb + '&w=65&h=65'): window.ROOT('resources/images/default.png');
			cover.fileId = data.id;
			cover.width = data.width;
			cover.height = data.height;

			this.$data = cover;

			var thumb = this.$el.find('.M-uploaderCoverThumb img');
			common.loadImage('default', cover.thumb, thumb);

			if(this.$.assist){
				this.$.assist.setData(data);
			}
		},
		// 销毁模块
		onChildDeleted: function(ev){
			this.fire('childDeleted', null, 'afterChildDeleted', this);
			return false;
		},
		afterChildDeleted: function(){
			this.destroy();
		},
		getValue: function(){
			// 如果是上传，fileId有值
			return {
				thumb: this.$data.thumb,
				fileId: this.$data.fileId,
				width: this.$data.width,
				height: this.$data.height
			};
		}
	});
	exports.cover = Cover;

	//资质证件
	var Certificate = Cover.extend({
		setData: function(data){
			if ( typeof data === "string" ) {
				data = {thumb : data};
			}

			var cover = {};
			var thumb = '';
			//兼容旧数据，如果http开头的url，则直接使用该url
			if (data.thumb && !data.thumb.indexOf('http'))
			{
				thumb = data.thumb;
			}
			else
			{
				thumb = data.thumb ? (data.thumb + '&w=65&h=65'): window.ROOT('resources/images/default.png');
			}
			cover.thumb = thumb;
			cover.fileId = data.id;
			cover.width = data.width;
			cover.height = data.height;

			this.$data = cover;

			var thumb = this.$el.find('.M-uploaderCoverThumb img');
			common.loadImage('default', cover.thumb, thumb);

			if(this.$.assist){
				this.$.assist.setData(data);
			}
		}
	});
	exports.certificatie = Certificate;

	var AddManually = Cover.extend({
		afterBuild: function(){
			var c = this.getConfig();
			var el = this.getDOM();

			if (el.prev().get()) {
				el.prev().find('.delete').click();
			}

			this.append('<div class="M-uploaderCoverThumb"><img alt="'+LANG('封面')+'" src="'+c.defaultImage+'" /></div>');

			// 控制状态模块
			this.create('assist', UploaderAssist, {
				'hasDelete': true,
				'target': this.$el,
				'hasPreview': true,
				'class': 'M-uploaderCoverStatus'
			});

			if(c.data){
				this.$.assist.update(true);
				this.setData(c.data);
			}
		},
		setData: function(data){
			if ( typeof data === "string" ) {
				data = {thumb : data};
			}

			var cover = {};
			cover.thumb = data.thumb ? (data.thumb + '&w=160&h=160'): window.ROOT('resources/images/default.png');
			cover.fileId = data.id;
			cover.width = data.width;
			cover.height = data.height;

			this.$data = cover;

			var thumb = this.$el.find('.M-uploaderCoverThumb img');
			common.loadImage('default', cover.thumb, thumb);

			if(this.$.assist){
				this.$.assist.setData(data);
			}
		}
	});
	exports.manually = AddManually;

});